package com.spring.sso.config.security.authentication.impl;

import com.alibaba.fastjson.JSON;
import com.beust.jcommander.internal.Lists;
import com.spring.sso.common.CommonResult;
import com.spring.sso.common.LoginAuthProtocol;
import com.spring.sso.config.common.AuthenticationConfig;
import com.spring.sso.config.common.Constant;
import com.spring.sso.config.common.DefaultUserDetails;
import com.spring.sso.entity.*;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author : pangfuzhong
 * @description
 * @date : 2021/9/25 16:04
 */
public class CommonService {

    public static CommonResult createResult() {
        CommonResult commonResult = new CommonResult();
        commonResult.setSuccess(Boolean.TRUE);
        commonResult.setMessage("处理成功");
        commonResult.setErrorCode("0");
        commonResult.setData(null);
        return commonResult;
    }

    public static void returnResponse(HttpServletResponse response, CommonResult commonResult) {
        response.setContentType(Constant.APPLICATION_JSON);
        response.setCharacterEncoding(Constant.CHARACTER_ENCODING_UTF8);
        try {
            response.getWriter().write(JSON.toJSONString(commonResult));
            response.getWriter().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static DefaultUserDetails loadUserByUsername(AuthenticationConfig authenticationConfig, String userName) {
        try {
            DefaultUserDetails userDetails = new DefaultUserDetails();
            // 查询用户
            SecurityUserEntityExample securityUserEntityExample = new SecurityUserEntityExample();
            securityUserEntityExample.createCriteria().andUserNameEqualTo(userName);
            List<SecurityUserEntity> securityUserEntityList = authenticationConfig.getSecurityUserEntityMapper().selectByExample(securityUserEntityExample);
            if(CollectionUtils.isEmpty(securityUserEntityList)) {
                throw new InternalAuthenticationServiceException("登陆失败,账号不存在");
            }

            SecurityUserEntity securityUserEntity = securityUserEntityList.get(0);
            userDetails.setUserName(securityUserEntity.getUserName());
            userDetails.setPassword(securityUserEntity.getPassword());
            //userDetails.setAge(securityUserEntity.getAge());
            //userDetails.setSex(securityUserEntity.getSex());

            // 查询角色权限
            /*SecurityUserRoleEntityExample securityUserRoleEntityExample = new SecurityUserRoleEntityExample();
            securityUserRoleEntityExample.createCriteria().andUserIdEqualTo(securityUserEntity.getId());
            List<SecurityUserRoleEntity> securityUserRoleEntityList = authenticationConfig.getSecurityUserRoleEntityMapper().selectByExample(securityUserRoleEntityExample);
            if(CollectionUtils.isEmpty(securityUserRoleEntityList)) {
                //userDetails.setAuthorities(Lists.newArrayList());
            }

            // 查询角色名
            List<Integer> roleIds = securityUserRoleEntityList.stream().map(securityUserRoleEntity -> securityUserRoleEntity.getRoleId()).collect(Collectors.toList());
            SecurityRoleEntityExample securityRoleEntityExample = new SecurityRoleEntityExample();
            securityRoleEntityExample.createCriteria().andIdIn(roleIds);
            List<SecurityRoleEntity> securityRoleEntityList = authenticationConfig.getSecurityRoleEntityMapper().selectByExample(securityRoleEntityExample);
            if(CollectionUtils.isEmpty(securityRoleEntityList)) {
                //userDetails.setAuthorities(Lists.newArrayList());
            }
            final List<SimpleGrantedAuthority> simpleGrantedAuthorityList = securityRoleEntityList.stream().map(securityRoleEntity -> new SimpleGrantedAuthority(securityRoleEntity.getRoleDesc())).collect(Collectors.toList());
            //userDetails.setAuthorities(simpleGrantedAuthorityList);
            //userDetails.setEnabled(Boolean.TRUE);*/
            return userDetails;
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 正常业务请求认证token
     *   1、验证token是否被踢掉
     *   2、验证redis是否存在,即是否过期
     *   3、校验token的完整性，是否被篡改
     * @param accessToken
     * @param commonResult
     * @return
     * */
    public static void authenticateTokenValid(AuthenticationConfig authenticationConfig, String accessToken, CommonResult commonResult) {
        RedisTemplate redisTemplate = authenticationConfig.getRedisTemplate();
        try {
            // 1、校验token的完整性，是否被篡改  10006
            Boolean wrongFul = authenticationConfig.getJwtTokenService().verifyTokenByRSA(accessToken);
            if(!wrongFul) {
                // 以篡改
                commonResult.setSuccess(Boolean.FALSE);
                commonResult.setErrorCode(Constant.TOKEN_INVALID_WRONGFUL_CODE);
                commonResult.setMessage(Constant.TOKEN_INVALID_WRONGFUL_MSG);
                return;
            }

            // 2、验证token是否被踢掉 10004
            String key = MessageFormat.format("{0}_{1}_{2}", Constant.OFFLINE_KEY, Constant.TOKEN_KEY_PREFIX, accessToken);
            if(redisTemplate.hasKey(key)) {
                // 不为空, 已经被踢
                commonResult.setSuccess(Boolean.FALSE);
                commonResult.setErrorCode(Constant.TOKEN_INVALID_KICK_OUT_CODE);
                commonResult.setMessage(Constant.TOKEN_INVALID_KICK_OUT_MSG);
                return;
            }

            // 3、验证redis是否存在,即是否过期 10005
            key = MessageFormat.format("{0}_{1}", Constant.TOKEN_KEY_PREFIX, accessToken);
            Object obj = redisTemplate.opsForValue().get(key);
            if(Objects.isNull(obj)) {
                // 为空, 已超过token有效时间
                commonResult.setSuccess(Boolean.FALSE);
                commonResult.setErrorCode(Constant.TOKEN_INVALID_OVERDUE_CODE);
                commonResult.setMessage(Constant.TOKEN_INVALID_OVERDUE_MSG);
                return;
            } else {
                LoginAuthProtocol loginAuthProtocol = JSON.parseObject(obj.toString(), LoginAuthProtocol.class);
                commonResult.setData(loginAuthProtocol);
            }

            // 4、token校验成功，执行续命
            redisTemplate.expire(accessToken, authenticationConfig.getTokenExpireTime(), TimeUnit.SECONDS);
        } catch (Exception e) {
            // 10007
            commonResult.setSuccess(Boolean.FALSE);
            commonResult.setErrorCode(Constant.TOKEN_CHECK_EXCEPTION_CODE);
            commonResult.setMessage(Constant.TOKEN_CHECK_EXCEPTION_MSG + ", " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 登出过程验证token是否有效
     * @param authenticationConfig
     * @param accessToken
     * @param commonResult
     * @return
     * */
    public static void logoutAuthenticateTokenValid(AuthenticationConfig authenticationConfig, String accessToken, CommonResult commonResult) {
        try {
            Boolean wrongFul = authenticationConfig.getJwtTokenService().verifyTokenByRSA(accessToken);
            if(!wrongFul) {
                // 不合法
                commonResult.setSuccess(Boolean.FALSE);
                commonResult.setErrorCode(Constant.TOKEN_INVALID_WRONGFUL_CODE);
                commonResult.setMessage(Constant.TOKEN_INVALID_WRONGFUL_MSG);
                return;
            }
        } catch (Exception e) {
            // 10007
            commonResult.setSuccess(Boolean.FALSE);
            commonResult.setErrorCode(Constant.TOKEN_CHECK_EXCEPTION_CODE);
            commonResult.setMessage(Constant.TOKEN_CHECK_EXCEPTION_MSG + ", " + e.getMessage());
            e.printStackTrace();
        }
    }
}
